#include "Chicken.h"
#include "ResourceManagers.h"
#include "ChickenDefGame.h"
#include <string>
#include "GUIOverlay.h"
#include "ComboSystem.h"

//#define VECTOR_MOD(v) sqrt(v.x*v.x+v.y*v.y)

#include <cstdio>
using namespace std;

const float Chicken::chickenVel=120;

// algunas constantes para la inercia del movimiento
const float maxIntertia=40;
const float damping=0.9;
const float timeToWaitShot=0.25f;
const float timeToWaitStunned=1.0f;

Chicken::Chicken(RenderWindow* wnd, PlayerControl *j,ChickenDefGame* _game):m_control(j),game(_game),AniSprite(*ImageManager::Instance()->GetImage("pollito_walk.png"),80,64){
	SetCenter(80/2.0f, 64/2.0f);
    Play(0,1);
    SetLoopSpeed(4);
    m_boundingRegion=wnd->GetView().GetRect();
	m_nest=Nest::Instance();
	eggThrowSound.SetBuffer(*SoundBufferManager::Instance()->GetBuffer("huevo.ogg"));

	Reset(wnd);
}

void Chicken::Reset(RenderWindow *wnd){
	SetPosition(wnd->GetWidth()/2, wnd->GetHeight()/2);
	timeSinceLastShot=0.0f;
	m_dir.x=0;
	m_dir.y=1;
	m_lastdir=m_dir;
	LeaveNest();

}

bool Chicken::OnNest(){
	Vector2f center=game->nest->GetPosition();
	Vector2f pos = GetPosition();
	float dist= sqrtf( (center.x-pos.x)*(center.x-pos.x)+ (center.y-pos.y)*(center.y-pos.y) );
		if(dist<50)
			return true;
	return false;
}

void Chicken::ChangeState(Status newStatus){
    //static Status oldStatus=IDLE; lo comente porque teniamos lios sinoy
	//con tener varias instancias

	if(newStatus==status) return;
    switch(newStatus){
        case MOVING_UP:
            Play(0,2);
            m_dir.x=0; m_dir.y=-1;
			m_lastdir=m_dir;
            // cuando se cambia bruscamente de direccion el movimiento
            // se descarta la inercia, para que solo tenga efecto cuando el
            // personaje pasa de moverse a quieto
            m_intertia.x=m_intertia.y=0;
			SetRotation(0);
        break;

        case MOVING_DOWN:
            Play(0,2);
            m_dir.x=0; m_dir.y=1;
			m_lastdir=m_dir;
            m_intertia.x=m_intertia.y=0;
			SetRotation(180);
        break;

        case MOVING_RIGHT:
            Play(0,2);
            m_dir.x=1; m_dir.y=0;
			m_lastdir=m_dir;
            m_intertia.x=m_intertia.y=0;
			SetRotation(270);
        break;

        case MOVING_LEFT:
            Play(0,2);
            m_dir.x=-1; m_dir.y=0;
			m_lastdir=m_dir;
            m_intertia.x=m_intertia.y=0;
			SetRotation(90);
        break;

        case IDLE:
            Play(0,1);
			m_dir.x=0; m_dir.y=0;
        break;

		case HATCHING:
            // ajusta la posicion al nido
            //printf("hatching...\n");
            SetPosition(Nest::Instance()->GetPosition());
            ComboSystem::Instance()->Activate(m_control);
            GUIOverlay::Instance()->SetPlayerHatching(0);

			// TODO: reproducir alguna animacion
			SetImage(*ImageManager::Instance()->GetImage("empoyando2.png"));
			SetFrameSize(89,96);
			SetCenter(44.5,48);
			SetLoopSpeed(5);
			Play();
        break;

		case STUNNED:
			timeSinceStunned=0.0f;
        break;
    }
    status=newStatus;
}

//#include <cstdio>
//using namespace std;

//metodo para disparar un huevo en la direccion que esta mirando
void Chicken::Shoot(){
	if(!pollito)
		return;

	if(timeSinceLastShot>timeToWaitShot){
		timeSinceLastShot=0.0f;
		Egg* egg=game->GetEgg();
		egg->Reset(GetPosition(),m_lastdir);
		eggThrowSound.SetLoop(false);
		eggThrowSound.Play();
	}
}

void Chicken::GotoGallina(){

	pollito=false;
	SetImage(*ImageManager::Instance()->GetImage("gallina_walk.png"));
	SetFrameSize(86,96);
	SetCenter(43,48);


}

void Chicken::GotoPollito(){

	GUIOverlay::Instance()->ShowPuffSprite(1.0f);

	SetImage(*ImageManager::Instance()->GetImage("pollito_walk.png"));
	SetFrameSize(80,64);
	SetCenter(40,32);
	pollito=true;

}

void Chicken::Update(float dt){
    // si estamos empollando solamente animamos, no nos interesa
    // mover ni censar controles
    if(status==HATCHING){
        AniSprite::Update();
        return;
    }


	if(OnNest()){
		if(m_control->ControlPressed(PlayerControl::CONTROL_BUTTON2)){
			//check if its our turn to hatch
			if(status!=HATCHING && m_nest->GetChicken()==this){
					ChangeState(HATCHING);
                    return;

            }

        }
    }

	//Weasel *w=game->CircleCollidesWithWeasels(GetPosition(),this->GetFrameCircleRadius());
	//if(w!=NULL){
	//	if(status==HATCHING){
	//		//perdimos
	//	}else{
	//		ChangeState(STUNNED);
	//	}
	//}

	if(status==STUNNED){
		if(timeSinceStunned>timeToWaitStunned)
			ChangeState(IDLE);
		timeSinceStunned+=dt;
	}else{
        // actualiza el estado en funcion de los controles
        if(m_control->ControlPressed(PlayerControl::CONTROL_UP)){
            ChangeState(MOVING_UP);
        }else if(m_control->ControlPressed(PlayerControl::CONTROL_DOWN)){
            ChangeState(MOVING_DOWN);
        }else if(m_control->ControlPressed(PlayerControl::CONTROL_RIGHT)){
            ChangeState(MOVING_RIGHT);
        }else if(m_control->ControlPressed(PlayerControl::CONTROL_LEFT)){
            ChangeState(MOVING_LEFT);
        }else{
            ChangeState(IDLE);
        }

        if(m_control->ControlPressed(PlayerControl::CONTROL_BUTTON1))
            Shoot();
        else
            timeSinceLastShot+=dt;


        AniSprite::Update();
        if(status!=IDLE){
            float mx=chickenVel*dt*m_dir.x, my=chickenVel*dt*m_dir.y;
            Move(mx, my);
            // si nos estamos moviendo, acumulamos inercia (hasta cierto punto)
            m_intertia.x+=mx;
            m_intertia.y+=my;
            if(fabs(m_intertia.x)>maxIntertia) m_intertia.x=maxIntertia*m_dir.x;
            if(fabs(m_intertia.y)>maxIntertia) m_intertia.y=maxIntertia*m_dir.y;
        }else{
            // cuando pasamos al reposo, nos seguimos moviendo igual por la inercia
            Move(m_intertia.x*dt, m_intertia.y*dt);
            // el rozamiento disipa la inercia
            m_intertia.x*=damping;
            m_intertia.y*=damping;
            // para evitar errores numericos
            if(fabs(m_intertia.x)<0.0001) m_intertia.x=0;
            if(fabs(m_intertia.y)<0.0001) m_intertia.y=0;
        }

	}
    // revisa que no se salga de la region de la pantalla
    sf::Vector2f p=GetPosition();
    if(p.x>m_boundingRegion.Right)    SetX(m_boundingRegion.Right);
    if(p.x<m_boundingRegion.Left)     SetX(m_boundingRegion.Left);
    if(p.y>m_boundingRegion.Bottom)   SetY(m_boundingRegion.Bottom);
    if(p.y<m_boundingRegion.Top)      SetY(m_boundingRegion.Top);

//    printf("%.2f - %.2f\n", m_intertia.x, m_intertia.y);
}


void Chicken::LeaveNest(){
	ChangeState(IDLE);
	ComboSystem::Instance()->Deactivate();
}



